package com.wind.plugin.window;

import com.intellij.lang.annotation.Annotation;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.markup.HighlighterLayer;
import com.intellij.openapi.editor.markup.HighlighterTargetArea;
import com.intellij.openapi.editor.markup.MarkupModel;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.XmlRecursiveElementVisitor;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;

import javax.swing.*;
import java.awt.*;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.wind.plugin.common.Constant.textCurAttributes;
import static com.wind.plugin.common.Common.shouldSkipCheck;
import static com.wind.plugin.common.Constant.textCurAttributesClass;
import static com.wind.plugin.common.OracleFunsEnum.isOracleFun;

public class Utils {

    private static final Pattern WHERE_IMCUSTNO_PATTERN = Pattern.compile(".*where[\\s\\S]*im_cust_no.*",  Pattern.CASE_INSENSITIVE);
    private static final Pattern INSERT_IMCUSTNO_PATTERN = Pattern.compile(".*insert[\\s\\S]*im_cust_no.*",  Pattern.CASE_INSENSITIVE);
    private static final Pattern ALL_FUNCS_PATTERN = Pattern.compile("\\b(\\w+)\\s*\\(.*?\\)",  Pattern.CASE_INSENSITIVE);

    // 检查 SQL WHERE 条件中是否包含 im_cust_no
    public static boolean containsMissingWhereImcustNo(String text) {
        Matcher matcher = WHERE_IMCUSTNO_PATTERN.matcher(text);
        return matcher.find();
    }

    // 检查 SQL WHERE 条件中是否包含 im_cust_no
    public static boolean containsMissingInsertImcustNo(String text) {
        Matcher matcher = INSERT_IMCUSTNO_PATTERN.matcher(text);
        return matcher.find();
    }


    public static VirtualFile findVirtualFile(String filePath) {
        return VirtualFileManager.getInstance().findFileByUrl("file://" + filePath);

    }

    public static void showErrorDialog(Component panel, String message) {
        JOptionPane.showMessageDialog(panel, message, "Error", JOptionPane.ERROR_MESSAGE);
    }

    public static void openFile(Project project, VirtualFile file) {
        FileEditorManager.getInstance(project).openFile(file, true);
    }

    public static int countSumOccurrencesInXmlFile(XmlFile xmlFile) {
        AtomicInteger sumCount = new AtomicInteger(0);
        xmlFile.accept(new XmlRecursiveElementVisitor() {
            @Override
            public void visitElement(PsiElement element) {
                super.visitElement(element);
                if (element instanceof XmlTag) {
                    XmlTag tag = (XmlTag) element;
                    if ("select".equals(tag.getName()) || "update".equals(tag.getName()) || "insert".equals(tag.getName()) || "delete".equals(tag.getName())) {
                        String textContent = tag.getValue().getText();
                        Matcher matcher = ALL_FUNCS_PATTERN.matcher(textContent);
                        while (matcher.find()) {
                            String functionName = matcher.group(1);
                            if (isOracleFun(functionName)) {
                                sumCount.incrementAndGet();
                            }
                        }
                    }
                }
            }
        });
        return sumCount.get();
    }

    public static int countMissingTInXmlFile(XmlFile xmlFile) {
        AtomicInteger missingTCount = new AtomicInteger(0);
        xmlFile.accept(new XmlRecursiveElementVisitor() {
            @Override
            public void visitElement(PsiElement element) {
                super.visitElement(element);
                if (element instanceof XmlTag) {
                    XmlTag tag = (XmlTag) element;
                    String sqlText = tag.getValue().getText();
                    if (shouldSkipCheck(tag)) {
                        return;
                    }
                    if ("select".equals(tag.getName()) || "update".equals(tag.getName()) || "delete".equals(tag.getName())) {
                        if (!containsMissingWhereImcustNo(sqlText)) {
                            missingTCount.incrementAndGet();
                        }
                    }else if ("insert".equalsIgnoreCase(tag.getName())) {
                        if (!containsMissingInsertImcustNo(sqlText)) {
                            missingTCount.incrementAndGet();
                        }
                    }
                }
            }
        });
        return missingTCount.get();
    }

    public static void highlightRange(PsiElement psiElement, AnnotationHolder holder, String message, int start, int end) {
        TextRange range = new TextRange(start, end);
        holder.createWarningAnnotation(range, message);
        Editor[] editors = EditorFactory.getInstance().getEditors(Objects.requireNonNull(psiElement.getContainingFile().getViewProvider().getDocument()));
        for (Editor editor : editors) {
            MarkupModel markupModel = editor.getMarkupModel();
            markupModel.addRangeHighlighter(start, end, HighlighterLayer.WARNING, textCurAttributes, HighlighterTargetArea.EXACT_RANGE);
        }
    }

    public static void annotateRange(int start, int end, AnnotationHolder holder, String message) {
        TextRange range = new TextRange(start, end);
        Annotation annotation = holder.createAnnotation(HighlightSeverity.INFORMATION,
                range,
                message);
        //Annotation annotation = holder.createWarningAnnotation(range, message);
//      annotation.setTextAttributes(DefaultLanguageHighlighterColors.CONSTANT);
//      annotation.setHighlightType(ProblemHighlightType.WEAK_WARNING);
//      annotation.setTextAttributes(DefaultLanguageHighlighterColors.CONSTANT);
        annotation.setEnforcedTextAttributes(textCurAttributes);
    }

}
